
import Vue from 'vue'
import http from 'axios'
import { accessToken, apiBaseURL } from '@/env'

var download = (function download () {
  let link
  let timeId
  return function (data, fileName, isExportBase64) {
    if (!data) return

    let url = !isExportBase64
      ? window.URL.createObjectURL(new Blob([data]))
      : window.URL.createObjectURL(base64ToBlob(data))

    if (!link) {
      link = document.createElement('a')
    }
    link.style.display = 'none'
    link.href = url
    link.setAttribute('download', fileName)
    document.body.appendChild(link)
    link.click()
    timeId = setTimeout(() => {
      link.parentNode.removeChild(link)
      clearTimeout(timeId)
    }, 200)
  }
})()

function bolb2string (blob, callback) {
  let reader = new FileReader()
  reader.readAsText(blob, 'utf-8')
  reader.onload = function (e) {
    callback(reader.result)
  }
}

function base64ToBlob (dataurl) {
  let arr = dataurl.split(',')
  let mime = arr[0].match(/:(.*?);/)[1]

  let bstr = atob(arr[1])
  let n = bstr.length
  let u8arr = new Uint8Array(n)

  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }

  return new Blob([u8arr], { type: mime })
}

function downloadUseLoading (loading) {
  const ctx = this
  return function (url, params, fileName) {
    ctx[loading] = true
    return new Promise((resolve, reject) => {
      http({
        method: 'get',
        url: apiBaseURL + '/' + url,
        params,
        responseType: 'blob',
        headers: { 'token': Vue.ls.get(accessToken) }
      }).then(res => {
        ctx[loading] = false
        if (res.data && res.data.type === 'application/json') {
          try {
            bolb2string(res.data, (str) => {
              const ret = JSON.parse(str)
              if (ret && ret.result !== 0) {
                return reject(new Error(ret.message))
              }
              download(res.data, fileName)
              resolve()
            })
          } catch (e) {
            reject(e)
          }
        } else {
          download(res.data, fileName)
          resolve()
        }
      }).catch(error => {
        ctx[loading] = false
        reject(error)
      })
    })
  }
}

function downloadBase64UseLoading (loading) {
  const ctx = this
  return function (url, params, fileName) {
    ctx[loading] = true
    return new Promise((resolve, reject) => {
      http({
        method: 'get',
        url: apiBaseURL + '/' + url,
        params,
        headers: { 'token': Vue.ls.get(accessToken) }
      }).then(res => {
        ctx[loading] = false

        if (res.data.result !== 0) {
          ctx.$message.warning(res.data.message)
          return
        }
        const { fileBaseString, fileName } = res.data.data

        function toBlob (dataurl) {
          let bstr = atob(dataurl)
          let n = bstr.length
          let u8arr = new Uint8Array(n)
          while (n--) {
            u8arr[n] = bstr.charCodeAt(n)
          }
          return new Blob([u8arr], {
            type: 'application/vnd.ms-excel'
          })
        }
        function download (data) {
          let link = document.createElement('a')
          let url = window.URL.createObjectURL(data)
          let timeId
          clearTimeout(timeId)

          link.style.display = 'none'
          link.href = url
          link.setAttribute('download', fileName)
          document.body.appendChild(link)
          link.click()
          timeId = setTimeout(() => {
            link.parentNode.removeChild(link)
            clearTimeout(timeId)
          }, 200)
        }
        let b = toBlob(fileBaseString)
        download(b, fileName, true)
      }).catch(error => {
        ctx[loading] = false
        reject(error)
      })
    })
  }
}

const httpDownload = (url, params, fileName) => {
  return new Promise((resolve, reject) => {
    http({
      method: 'get',
      url: apiBaseURL + '/' + url,
      params,
      responseType: 'blob',
      headers: { 'token': Vue.ls.get(accessToken) }
    }).then(res => {
      if (res.data.type === 'application/json') {
        try {
          bolb2string(res.data, (str) => {
            const ret = JSON.stringify(str)
            if (ret && ret.result !== 0) {
              return reject(new Error(ret.message))
            }
            download(res.data, fileName)
            resolve()
          })
        } catch (e) {
          reject(e)
        }
      } else {
        download(res.data, fileName)
        resolve()
      }
    }).catch(error => reject(error))
  })
}

export default httpDownload
export {
  downloadBase64UseLoading,
  downloadUseLoading
}
